package com.cse587.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

public class Classification {
	private Map<Integer, ArrayList<Pair>> clusters;
	private List<Pair> collection;
	private List<Double> currentSum;
	private List<Double> means;
	private boolean status;
	private int groupNumber;
	int count;
	
	public Classification(int number){
		count = 0;
		collection = new ArrayList<Pair>();
		groupNumber = number;
		clusters = new HashMap< Integer, ArrayList<Pair> >();
		currentSum = new ArrayList<Double>();
		means = new ArrayList<Double>();
		status = false;
		for (int i = 0; i < number; i++) {
			clusters.put(i, new ArrayList<Pair>());
			currentSum.add(0.0);
		}
	}
		
	/////////////////////////////////////////////
	public void init(){
		Random randomGenerator = new Random();
		for (int i = 0; i < groupNumber; i++) {
			int randomIndex = randomGenerator.nextInt(collection.size()-1);
			means.add(collection.get(randomIndex).getValue());
		}
	}
	
	public void classify(){
		if( status ) return;
		System.out.println(means);
		count++;
		for (Pair p : collection) {
			partitionPair(p);
		}
		status = true;
		for (int i=0; i<groupNumber;i++) {
			double currentMean = Math.round( currentSum.get(i) / clusters.get(i).size() );
			if( Math.abs(currentMean - means.get(i)) > 1.0 ){
				status = false;
			}
			means.set(i, currentMean);
		}
		if( !status ){
			emptyAllCluster();
			classify();
		}
		
		return;
	}
	
	private void partitionPair(Pair p){
		int clusterIndex = -1;
		double minDist = 9999999999999999.0;
		int i = 0;
		for( double d : means ){
			double dist = Math.abs(p.getValue() - d);
			if( dist < minDist ){
				minDist = dist;
				clusterIndex = i; 
			}
			i++;
		}
		
		clusters.get(clusterIndex).add(p);
		double newSum = currentSum.get(clusterIndex) + p.getValue();
		currentSum.set(clusterIndex, newSum);
	}
	
	private void emptyAllCluster(){
		int i = 0;
		for (Map.Entry<Integer, ArrayList<Pair>> entry: clusters.entrySet() ) {
			entry.getValue().clear();
			currentSum.set(i, 0.0);
			i++;
		}
	}
	////////////////////stupid getter and setter
	public Map<Integer, ArrayList<Pair>> getClusters() {
		return clusters;
	}

	public void setClusters(Map<Integer, ArrayList<Pair>> clusters) {
		this.clusters = clusters;
	}
	public List<Double> getMeans() {
		return means;
	}
	public void setMeans(List<Double> means) {
		this.means = means;
	}
	public int getGroupNumber() {
		return groupNumber;
	}
	public void setGroupNumber(int groupNumber) {
		this.groupNumber = groupNumber;
	}

	public List<Pair> getCollection() {
		return collection;
	}

	public void setCollection(List<Pair> collection) {
		this.collection = collection;
	}

	public List<Double> getCurrentSum() {
		return currentSum;
	}

	public void setCurrentSum(List<Double> currentSum) {
		this.currentSum = currentSum;
	}
	
}
